import json
import os
import re
import time
import pandas as pd
from django.urls import reverse
from django.utils import timezone
# from django.http import HttpResponse
# from pyecharts.charts import Bar
# from pyecharts import options as opts
from django.contrib.auth.decorators import login_required
from django.shortcuts import render, redirect
import requests
from django.views.decorators.http import require_POST
from fake_useragent import UserAgent
from login.models import NormalUser
from spider.models import Product, Author, Category, Comment
from spider.pinglun import pinglun
from spider.views import get_bilibili_danmu, get_real_time, json_response, json_error
from .visual import get_all_chart, get_category_top1_play, get_top18_category_pie, wordcloud_view, sentiment_pie_view, \
    compare_with_top5, analysis_chart, wordcloud2_view, sentiment2_pie_view, audience_activity_combine

JsonResponse = json_response
JsonError = json_error


def spider(bv):
    ua = UserAgent(os="Windows")
    headers = {
        'Cookie': "SESSDATA=f0e5216b%2C1761694484%2C13844%2A52CjB6RXKJuN8f8rpK4nnJCCZepHNMSqa_RlhGP2kiCWZHsNuAn2TF4wY9mBkYMv9AfEcSVm9KN2F4Yl9FaVpEZmNCM0tZamRFTjl4TjFRWjRvU3RqNGJsTHBCY3U0ZHdTYzBuM2I5TTlwb2d3bnpJR0NUUWNFdlF1WHdyQkw5Z05GNEZfdG5iTE5nIIEC",
        'Accept': 'application/json, text/plain, */*',
        'Origin': 'https://www.bilibili.com',
        'Host': 'api.bilibili.com',
        'User-Agent': ua.random,
        'Accept-Language': 'zh-cn',
        'Connection': 'keep-alive',
        'Referer': 'https://www.bilibili.com/v/popular/rank/all'
    }
    url = 'https://api.bilibili.com/x/web-interface/wbi/view'
    params = {
        'bvid': bv
    }
    response = requests.get(url, params=params, headers=headers)
    # print(response.text)
    data_json = response.json()
    data = data_json['data']
    video_url = f'https://www.bilibili.com/video/{bv}/'
    # 获取或创建作者
    author, _ = Author.objects.get_or_create(name=data['owner']['name'], UID=data['owner']['mid'])
    tid = data['tid']
    if tid in [1, 24, 25, 47, 257, 210, 86, 253, 27]:
        tab_name = 'animation'
    elif tid in [3, 28, 31, 30, 59, 193, 29, 130, 243, 244]:
        tab_name = 'music'
    elif tid in [129, 20, 154, 156, 198, 199, 200, 255]:
        tab_name = 'music'
    elif tid in [4, 17, 171, 172, 65, 173, 121, 136, 19]:
        tab_name = 'game'
    elif tid in [36, 201, 124, 228, 207, 208, 209, 229, 122]:
        tab_name = 'knowledge'
    elif tid in [188, 95, 230, 231, 232, 233]:
        tab_name = 'technology'
    elif tid in [234, 235, 249, 164, 236, 237, 238]:
        tab_name = 'motion'
    elif tid in [223, 258, 245, 246, 247, 248, 240, 227, 176]:
        tab_name = 'car'
    elif tid in [160, 138, 250, 251, 239, 161, 162, 21, 254]:
        tab_name = 'live'
    elif tid in [211, 76, 212, 213, 214, 215]:
        tab_name = 'food'
    elif tid in [217, 218, 219, 220, 221, 222, 75]:
        tab_name = 'animal'
    elif tid in [119, 22, 26, 126, 216, 127]:
        tab_name = 'ghost_animal'
    elif tid in [155, 157, 252, 158, 159]:
        tab_name = 'vogue'
    elif tid in [5, 71, 241, 242, 137]:
        tab_name = 'amusement'
    elif tid in [181, 182, 183, 85, 184, 256]:
        tab_name = 'film'
    elif tid in [167, 153, 168, 169, 170, 195]:
        tab_name = 'original'
    elif tid in [155, 157, 252, 158, 159]:
        tab_name = 'film'
    else:
        tab_name = 'all'
    # 获取或创建分类
    category, _ = Category.objects.get_or_create(category_name=tab_name)
    title = data['title']
    title = re.sub(r'[^\x00-\x7F\u4e00-\u9fff]', '', title)
    product, _ = Product.objects.get_or_create(
        BVID=bv,
        defaults={
            'title': title,
            'category': category,
            'video_url': video_url,
            'score_list': data['score'] if 'score' in data else 0,
            'play_cnt_list': data['stat']['view'],
            'danmu_cnt_list': data['stat']['danmaku'],
            'coin_cnt_list': data['stat']['coin'],
            'like_cnt_list': data['stat']['like'],
            'dislike_cnt_list': data['stat']['dislike'],
            'share_cnt_list': data['stat']['share'],
            'favorite_cnt_list': data['stat']['favorite'],
            'reply_cnt_list': data['stat']['reply']
        }
    )
    product.author_list.add(author)

    if os.path.exists(f'./upload/pics/{bv}.png'):
        print(f"视频 {bv} 的封面已存在，跳过封面爬取")
    else:
        save_dir = './upload/pics'
        if not os.path.exists(save_dir):
            os.makedirs(save_dir)

        pic_url = data['pic']
        pic_url_response = requests.get(pic_url)
        print(f"正在爬取视频 {bv} 的封面")
        with open(f'./upload/pics/{bv}.png', 'wb') as picfile:
            picfile.write(pic_url_response.content)

    # 爬取弹幕
    danmu_list, cid = get_bilibili_danmu(video_url[:-1])

    # 保存弹幕数据到数据库
    for d in danmu_list:
        data_split = d['p'].split(',')
        temp_time = time.localtime(int(data_split[4]))
        danmu_time = time.strftime("%Y-%m-%d %H:%M:%S", temp_time)
        # 将朴素的日期时间对象转换为带时区的日期时间对象
        danmu_time = timezone.make_aware(pd.to_datetime(danmu_time))
        time_loc = get_real_time(v_str=data_split[0])
        Comment.objects.create(
            BVID=product,  # 外键关联 Product
            video_url_list=video_url,
            danmu_url_list=f'https://api.bilibili.com/x/v1/dm/list.so?oid={cid}',
            time_list=danmu_time,
            time_loc_list=time_loc,
            text_list=d.text
        )


def index(request):
    is_logged_in = request.session.get('is_logged_in', False)
    # 获取各分类分区 TOP-1 播放量折线图
    line1 = get_category_top1_play()
    line1_html = line1.render_embed()
    comment_number = Comment.objects.count()
    product_number = Product.objects.count()
    author_number = Author.objects.count()
    products_top20 = Product.objects.filter().order_by('-play_cnt_list')[:20]
    top1 = Product.objects.exclude(category__category_name='all').order_by('-play_cnt_list').first().category.category_name
    category_name = {
        'all': '全分区',
        'animation': '动画',
        'music': '音乐',
        'dance': '舞蹈',
        'game': '游戏',
        'knowledge': '知识',
        'technology': '科技',
        'motion': '运动',
        'car': '汽车',
        'live': '生活',
        'food': '美食',
        'animal': '动物',
        'ghost_animal': '鬼畜',
        'vogue': '时尚',
        'amusement': '娱乐',
        'film': '影视',
        'original': '原创',
        'newcomer': '新人',
    }
    # 获取按播放、点赞、投币降序排列前 top-18 各分区饼状图占比
    pie = get_top18_category_pie()
    pie_html = pie.render_embed()
    context = {
        'line1_html': line1_html,
        'pie_html': pie_html,
        'products_top20': products_top20,
        'comment_number': comment_number,
        'product_number': product_number,
        'author_number': author_number,
        'top1': category_name[top1],
        'is_logged_in': is_logged_in
    }
    if is_logged_in:
        username = request.session.get('username')
        user = NormalUser.objects.get(username=username)
        context['user'] = user

    return render(request, 'index.html', context)


def return_chart(types):
    bar1, line1, line2, bar2 = get_all_chart(types)
    bar1_html = bar1.render_embed()
    line1_html = line1.render_embed()
    line2_html = line2.render_embed()
    bar2_html = bar2.render_embed()

    all_products_top20 = Product.objects.filter(category__category_name=types).order_by('-play_cnt_list')[:20]

    context = {
        'bar1_html': bar1_html,
        'line1_html': line1_html,
        'line2_html': line2_html,
        'bar2_html': bar2_html,
        'all_products_top20': all_products_top20
    }

    return context

def details(request):
    bv = request.GET.get('bv')
    is_logged_in = request.session.get('is_logged_in')
    product = Product.objects.get(BVID=bv)
    wordcloud_view_html = wordcloud_view(bv).render_embed()
    sentiment_pie_view_html = sentiment_pie_view(bv).render_embed()
    compare_with_top5_html = compare_with_top5(bv).render_embed()
    analysis_chart_html = analysis_chart(bv).render_embed()
    wordcloud2_view_html = wordcloud2_view(bv).render_embed()
    sentiment2_pie_view_html = sentiment2_pie_view(bv).render_embed()
    audience_activity_combine_html = audience_activity_combine(bv).render_embed()
    context = {
        'is_logged_in': is_logged_in,
        'wordcloud_view':wordcloud_view_html,
        'sentiment_pie_view': sentiment_pie_view_html,
        'compare_with_top5': compare_with_top5_html,
        'analysis_chart': analysis_chart_html,
        'wordcloud2_view': wordcloud2_view_html,
        'audience_activity_combine': audience_activity_combine_html,
        'sentiment2_pie_view': sentiment2_pie_view_html,
        'product': product
    }
    return render(request, 'details.html', context)


# @require_POST
# @login_required
def search(request):
    if request.session.get('is_logged_in'):
        if request.method == "POST":
            data = json.loads(request.body)
            bv = data.get('bv')
            if Comment.objects.filter(BVID__BVID=bv).exists():
                print(f"视频 {bv} 的弹幕已存在，跳过弹幕爬取")
                if os.path.exists(f'./upload/comment/{bv}_评论.csv'):
                    print(f"视频 {bv} 的评论已存在，跳过评论爬取")
                else:
                    pinglun(bv=bv)
                url = f'{reverse("main:details")}?bv={bv}'
                print(url)
                return JsonResponse({'status': 200, 'url': url})
            else:
                spider(bv=bv)
                pinglun(bv=bv)
                url = f'{reverse("main:details")}?bv={bv}'
                print(url)
                return JsonResponse({'status': 200, 'url': url})
        if request.method == "GET":
            code = request.GET.get('code', 405)
            error_string = request.GET.get('error_string', "未知错误")
            return JsonResponse({'status': code, 'message': error_string})
    else:
        return JsonResponse({'status': 401, 'message': '请先登录'})

# @require_POST
# @login_required
def details_refresh(request):
    if request.session.get('is_logged_in'):
        if request.method == "POST":
            data = json.loads(request.body)
            bv = data.get('bv')
            spider(bv=bv)
            pinglun(bv=bv)
            url = f'{reverse("main:details")}?bv={bv}'
            print(url)
            return JsonResponse({'status': 200, 'url': url})

        if request.method == "GET":
            code = request.GET.get('code', 405)
            error_string = request.GET.get('error_string', "未知错误")

            return JsonError(error_string=error_string, code=code)
    else:
        return redirect('login:login')


def all_chart(request):
    context = return_chart('all')
    is_logged_in = request.session.get('is_logged_in')
    if is_logged_in:
        username = request.session.get('username')
        user = NormalUser.objects.get(username=username)
        context['user'] = user
        context['is_logged_in'] = is_logged_in
    return render(request, 'all_chart.html', context)


def animation_chart(request):
    context = return_chart('animation')
    is_logged_in = request.session.get('is_logged_in')
    if is_logged_in:
        username = request.session.get('username')
        user = NormalUser.objects.get(username=username)
        context['user'] = user
        context['is_logged_in'] = is_logged_in
    return render(request, 'animation_chart.html', context)


def music_chart(request):
    context = return_chart('music')
    is_logged_in = request.session.get('is_logged_in')
    if is_logged_in:
        username = request.session.get('username')
        user = NormalUser.objects.get(username=username)
        context['user'] = user
        context['is_logged_in'] = is_logged_in
    return render(request, 'music_chart.html', context)


def dance_chart(request):
    context = return_chart('dance')
    is_logged_in = request.session.get('is_logged_in')
    if is_logged_in:
        username = request.session.get('username')
        user = NormalUser.objects.get(username=username)
        context['user'] = user
        context['is_logged_in'] = is_logged_in
    return render(request, 'dance_chart.html', context)


def game_chart(request):
    context = return_chart('game')
    is_logged_in = request.session.get('is_logged_in')
    if is_logged_in:
        username = request.session.get('username')
        user = NormalUser.objects.get(username=username)
        context['user'] = user
        context['is_logged_in'] = is_logged_in
    return render(request, 'game_chart.html', context)


def knowledge_chart(request):
    context = return_chart('knowledge')
    is_logged_in = request.session.get('is_logged_in')
    if is_logged_in:
        username = request.session.get('username')
        user = NormalUser.objects.get(username=username)
        context['user'] = user
        context['is_logged_in'] = is_logged_in
    return render(request, 'knowledge_chart.html', context)


def technology_chart(request):
    context = return_chart('technology')
    is_logged_in = request.session.get('is_logged_in')
    if is_logged_in:
        username = request.session.get('username')
        user = NormalUser.objects.get(username=username)
        context['user'] = user
        context['is_logged_in'] = is_logged_in
    return render(request, 'technology_chart.html', context)


def motion_chart(request):
    context = return_chart('motion')
    is_logged_in = request.session.get('is_logged_in')
    if is_logged_in:
        username = request.session.get('username')
        user = NormalUser.objects.get(username=username)
        context['user'] = user
        context['is_logged_in'] = is_logged_in
    return render(request, 'motion_chart.html', context)


def car_chart(request):
    context = return_chart('car')
    is_logged_in = request.session.get('is_logged_in')
    if is_logged_in:
        username = request.session.get('username')
        user = NormalUser.objects.get(username=username)
        context['user'] = user
        context['is_logged_in'] = is_logged_in
    return render(request, 'car_chart.html', context)


def live_chart(request):
    context = return_chart('live')
    is_logged_in = request.session.get('is_logged_in')
    if is_logged_in:
        username = request.session.get('username')
        user = NormalUser.objects.get(username=username)
        context['user'] = user
        context['is_logged_in'] = is_logged_in
    return render(request, 'live_chart.html', context)


def food_chart(request):
    context = return_chart('food')
    is_logged_in = request.session.get('is_logged_in')
    if is_logged_in:
        username = request.session.get('username')
        user = NormalUser.objects.get(username=username)
        context['user'] = user
        context['is_logged_in'] = is_logged_in
    return render(request, 'food_chart.html', context)


def animal_chart(request):
    context = return_chart('animal')
    is_logged_in = request.session.get('is_logged_in')
    if is_logged_in:
        username = request.session.get('username')
        user = NormalUser.objects.get(username=username)
        context['user'] = user
        context['is_logged_in'] = is_logged_in
    return render(request, 'animal_chart.html', context)


def ghost_animal_chart(request):
    context = return_chart('ghost_animal')
    is_logged_in = request.session.get('is_logged_in')
    if is_logged_in:
        username = request.session.get('username')
        user = NormalUser.objects.get(username=username)
        context['user'] = user
        context['is_logged_in'] = is_logged_in
    return render(request, 'ghost_animal_chart.html', context)


def vogue_chart(request):
    context = return_chart('vogue')
    is_logged_in = request.session.get('is_logged_in')
    if is_logged_in:
        username = request.session.get('username')
        user = NormalUser.objects.get(username=username)
        context['user'] = user
        context['is_logged_in'] = is_logged_in
    return render(request, 'vogue_chart.html', context)


def amusement_chart(request):
    context = return_chart('amusement')
    is_logged_in = request.session.get('is_logged_in')
    if is_logged_in:
        username = request.session.get('username')
        user = NormalUser.objects.get(username=username)
        context['user'] = user
        context['is_logged_in'] = is_logged_in
    return render(request, 'amusement_chart.html', context)


def film_chart(request):
    context = return_chart('film')
    is_logged_in = request.session.get('is_logged_in')
    if is_logged_in:
        username = request.session.get('username')
        user = NormalUser.objects.get(username=username)
        context['user'] = user
        context['is_logged_in'] = is_logged_in
    return render(request, 'film_chart.html', context)


def original_chart(request):
    context = return_chart('original')
    is_logged_in = request.session.get('is_logged_in')
    if is_logged_in:
        username = request.session.get('username')
        user = NormalUser.objects.get(username=username)
        context['user'] = user
        context['is_logged_in'] = is_logged_in
    return render(request, 'original_chart.html', context)


def newcomer_chart(request):
    context = return_chart('newcomer')
    is_logged_in = request.session.get('is_logged_in')
    if is_logged_in:
        username = request.session.get('username')
        user = NormalUser.objects.get(username=username)
        context['user'] = user
        context['is_logged_in'] = is_logged_in
    return render(request, 'newcomer_chart.html', context)
